package cn.yzj.utils;

import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.beans.BeanUtils;

import javax.net.ssl.SSLContext;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Http 请求工具类
 *
 * @author gzkemays
 * @since 2022/1/14 20:39
 */
public class HttpUtils {
  /**
   * 获取有参列表对象
   *
   * @param map 请求数据
   * @return 有参列表对象
   */
  public static List<NameValuePair> getPairListByMap(Map<String, Object> map) {
    List<NameValuePair> list = new ArrayList<>();
    if (!map.isEmpty()) {
      for (Map.Entry<String, Object> entry : map.entrySet()) {
        list.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
      }
    }
    return list;
  }

  /**
   * 获取无参 http get 对象
   *
   * @param url 请求地址
   * @return {@link HttpGet}
   */
  public static HttpGet getHttpGet(String url) {
    return new HttpGet(url);
  }

  /**
   * 获取有参 http get 对象
   *
   * @param url 请求地址
   * @param map 请求参数
   * @return {@link HttpGet}
   */
  public static HttpGet getDataGet(String url, Map<String, Object> map) {
    HttpGet httpGet = getHttpGet(url);
    List<NameValuePair> list = getPairListByMap(map);
    if (list.size() > 0) {
      String param = URLEncodedUtils.format(list, "UTF-8");
      httpGet.setURI(URI.create(url + "?" + param));
    }
    return httpGet;
  }

  /**
   * 获取无参 http post 对象
   *
   * @param url 请求地址
   * @return {@link HttpPost}
   */
  public static HttpPost getHttpPost(String url) {
    return new HttpPost(url);
  }

  /**
   * 获取表单请求 post
   *
   * @param url 请求地址
   * @param map 表单对应键值对
   * @return {@link HttpPost}
   */
  public static HttpPost getUrlEncodedFormPost(
      String url, Map<String, Object> map, Charset charset) {
    HttpPost httpPost = new HttpPost(url);
    List<NameValuePair> list = getPairListByMap(map);
    if (list.size() > 0) {
      UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, charset);
      httpPost.setEntity(urlEncodedFormEntity);
    }
    return httpPost;
  }

  /**
   * http json post 请求
   *
   * @param url 请求地址
   * @param param json 字符串
   * @return {@link HttpPost}
   */
  public static HttpPost getPostJson(String url, String param) {
    StringEntity entity = new StringEntity(param, "utf-8");
    entity.setContentType("application/json");
    HttpPost httpPost = new HttpPost(url);
    httpPost.setEntity(entity);
    return httpPost;
  }

  /**
   * 获取 cookie
   *
   * <p>将 Cookie name value 以 name=value; 的形式拼接为字符串
   *
   * @param store cooke 存储器
   * @return cookie 字符串
   */
  public static String getCookie(CookieStore store) {
    List<Cookie> cookies = store.getCookies();
    StringBuilder tempcookies = new StringBuilder();
    for (Cookie c : cookies) {
      tempcookies.append(c.getName()).append("=").append(c.getValue()).append(";");
    }
    return tempcookies.toString();
  }

  /** HttpClient 线程池 */
  public static PoolingHttpClientConnectionManager poolingHttpClient() {
    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    cm.setMaxTotal(200);
    cm.setDefaultMaxPerRoute(50);
    return cm;
  }

  /** 忽略 ssl 证书 */
  public static CloseableHttpClient getIgnoreSslClient() throws Exception {
    SSLContext sslContext =
        SSLContexts.custom()
            .loadTrustMaterial(
                null,
                new TrustStrategy() {
                  @Override
                  public boolean isTrusted(X509Certificate[] x509Certificates, String s)
                      throws CertificateException {
                    return true;
                  }
                })
            .build();
    // 创建httpClient
    return HttpClients.custom()
        .setSSLContext(sslContext)
        .setSSLHostnameVerifier(new NoopHostnameVerifier())
        .build();
  }
}
